package utils

import (
	"database/sql/driver"
	"fmt"
	"time"
)

const (
	TimeFormat    = "2006-01-02 15:04:05"
	TimeFormatDay = "2006/01/02"
	timezone      = "Asia/Shanghai"
)

var shanghaiLoc *time.Location

func init() {
	var err error
	shanghaiLoc, err = time.LoadLocation(timezone)
	if err != nil {
		shanghaiLoc = time.FixedZone("CST", 8*3600) // 明确 fallback 到 +8
	}
}

// GetNow 返回当前北京时间
func GetNow() time.Time {
	return time.Now().In(shanghaiLoc)
}

// GetNowDate 返回当前日期时间字符串（格式：2006-01-02 15:04:05）
func GetNowDate() string {
	return GetNow().Format(TimeFormat)
}

// GetNowDay 返回当前日期字符串（格式：2006/01/02）
func GetNowDay() string {
	return GetNow().Format(TimeFormatDay)
}

// NewTimeNow 构造当前北京时间 Time
func NewTimeNow() Time {
	return Time{GetNow()}
}

// Time 是自定义的时间类型，始终使用北京时间
type Time struct {
	time.Time
}

// MarshalJSON 实现 JSON 序列化
func (t Time) MarshalJSON() ([]byte, error) {
	if t.IsZero() {
		return []byte(`""`), nil
	}
	return []byte(`"` + t.In(shanghaiLoc).Format(TimeFormat) + `"`), nil
}

// UnmarshalJSON 实现 JSON 反序列化
func (t *Time) UnmarshalJSON(data []byte) error {
	str := string(data)
	if str == "null" || str == `""` {
		t.Time = time.Time{}
		return nil
	}
	str = trimQuotes(str)
	parsed, err := time.ParseInLocation(TimeFormat, str, shanghaiLoc)
	if err != nil {
		return fmt.Errorf("invalid time format: %s", str)
	}
	t.Time = parsed
	return nil
}

// Value 实现 driver.Valuer 接口（用于数据库写入）
func (t Time) Value() (driver.Value, error) {
	if t.IsZero() {
		return nil, nil
	}
	return t.Time, nil
}

// Scan 实现 sql.Scanner 接口（用于数据库读取）
func (t *Time) Scan(v interface{}) error {
	switch value := v.(type) {
	case time.Time:
		t.Time = value.In(shanghaiLoc)
		return nil
	default:
		return fmt.Errorf("cannot convert %v to timestamp", v)
	}
}

// String 默认返回北京时间格式化字符串
func (t Time) String() string {
	if t.IsZero() {
		return ""
	}
	return t.In(shanghaiLoc).Format(TimeFormat)
}

// Time 返回底层 time.Time（可选）
func (t Time) UTC() time.Time {
	return t.Time
}

// trimQuotes removes surrounding quotes from a JSON string
func trimQuotes(s string) string {
	if len(s) >= 2 && s[0] == '"' && s[len(s)-1] == '"' {
		return s[1 : len(s)-1]
	}
	return s
}
